﻿using FinallyArchive__Comm;
using FinallyArchive__Dto;
using Mapster;

namespace FinallyArchive__Application.CURDBaseService
{
    /// <summary>
    /// 泛型<T> 占位符,可以存放五大约束,所以泛型 可以代替任何类型
    /// 基类约束、借口约束、new()构造函数约束、引用或值类型约束、组合约束
    /// 这里使用的是四个泛型占位符,有实体,输出显示DTO,输入占位符DTO,搜索占位符DTO,最后再跟一个Key主键
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseService<TEntity, TEntityInputDto, TEntityOutputDto, TEntitySearchDto, Key> : IBaseService<TEntity, TEntityInputDto, TEntityOutputDto, TEntitySearchDto,Key> where TEntity : class, new()
        where TEntityInputDto : class, new()
        where TEntityOutputDto : class, new()
        where TEntitySearchDto : class, new()
    {
        /// <summary>
        /// 构造函数 构造函数注入常用于在服务构建上定义和获取服务依赖
        /// 在服务构造函数中明确地定义必需的依赖。因此该服务在没有这些依赖时无法被构造。
        /// 将注入的依赖赋值给只读（readonly）的字段或属性(为了防止在内部方法中意外地赋予其他值)。
        /// ASP.NET Core 的标准依赖注入容器不支持属性注入。但是你可以使用其他容器支持属性注入
        /// </summary>
        /// <param name="context"></param>
        private readonly FinallyArchiveContext _context;
        public BaseService(FinallyArchiveContext context)
        {
            //注入
            _context = context;
        }
        /// <summary>
        /// 创建泛型添加
        /// 类型要和返回类型一致
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int AddEntity(TEntityInputDto entity)
        {
            //要用Mapster包转化数据源,因为我们用的是插入DTO所以在添加的时候没办法添加到数据库里面
            //所以就要用Mapster把DTO转化成实体数据源再存入数据库里面
            var Addentity = entity.Adapt<TEntity>();
            //这一步是添加刚转化完成的Addentity
            _context.Add(Addentity);
            //最后返回我们的插入DTO
            return _context.SaveChanges();
        }
        /// <summary>
        /// 创建泛型显示
        /// IQueryable和List不同的是List显示 是全部的表数据
        /// 而IQueryable接口只在供查询提供程序实现,不会直接显示全部的表数据
        /// 在大型数据中使用IQueryable会好许多
        /// 类型要和返回类型一致
        /// </summary>
        /// <returns></returns>
        public IQueryable<TEntityOutputDto> GetListAll()
        {
            //查询的话一定是要和数据库有联系的所以,直接差实体
            IQueryable<TEntity> lst = _context.Set<TEntity>().AsQueryable();
            //但是实体里面的字段又不想直接显示出来,所以要显示DTO就要使用Mapster转化成DTO
            return lst.Adapt<IQueryable<TEntityOutputDto>>();
        }


        /// <summary>
        /// 创建泛型删除
        /// 类型要和返回类型一致
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public TEntityOutputDto DelTEntity(int id)
        {
            //要用Mapster包转化数据源,因为我们用的是显示DTO所以在删除的时候没办法删除到数据库里面
            //所以就要用Mapster把DTO转化成实体数据源再删除数据库里面的数据
            var del = id.Adapt<TEntity>();
            //这一步是删除操作
            _context.Remove(del);
            //最后返回我们的显示DTO
            return _context.Adapt<TEntityOutputDto>();
        }
        /// <summary>
        /// 创建泛型修改
        /// 类型要和返回类型一致
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public int UpTEntity(TEntity user)
        {
           _context.Update(user);
            return _context.SaveChanges();
        }

        /// <summary>
        /// 查询一条消息,用于信息显示
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public TEntity InfoSearch(int id) 
        {
            var lst = _context.Set<TEntity>().Find(id);
            return lst;
        }
    }
}